#ifndef INTERRAPT_H
#define INTERRAPT_H

//#include <i386.h>

/*Сохраняет все регистры общего назначения в стеке
* Вызывает функцию обработчика прерывания
* Разрешает контроллеру возобновить прерывания
* Восстанавливает регистры из стека
* Возврат из прерывания
*/
#define INT_HANDLER(IFUNC) \
    void IFUNC (void); \
    asm(#IFUNC":"); \
    asm("pusha"); \
    asm("call _Z11_" #IFUNC"v");\
    asm("movb $0x20, %al"); \
    asm("outb %al, $0x20"); \
    asm("popa"); \
    asm("iret"); \
    void _ ## IFUNC()

/*
*Тоже самое, но еще извлекает из стека код ошибки
*/

//__uint32_t	INT_ERR;

#define INT_HANDLER_ERR(func) void func (void);\
 asm(#func ": pop INT_ERR \n pusha");\
 asm("call _" #func " \n popa \n iret \n");\
 void _ ## func(void)


/*Шлюз прерывания*/
/*
struct InterraptGate{
    unsigned	looffset:16;		//Младшие 2 байта смещения
    unsigned	selector:16;		//Селектор сегмента кода
    unsigned	reserved:8;		//Зарезервированы
    unsigned	type:5;		//Тип дескриптора
    unsigned	dpl:2;		//Уровень привелегий
    unsigned	present:1;		//Бит присутствия
    unsigned	hioffset:16;		//Старшие 2 байта смещения
};


class Interrapt{
	InterraptGate	*IDT;
	public:
		inline void intOn(){
			asm("sti");
		}
		inline void intOff(){
			asm("cli");
		}
		void setInterrapt(void (*i_addr)(), uint8 i_nr, uint8 i_type){
			IDT[i_nr].looffset = (uint16)((uint32)i_addr);
			IDT[i_nr].selector = SYS_CODE_SEL;
			IDT[i_nr].reserved = 0;
			IDT[i_nr].type = i_type;
			IDT[i_nr].dpl = UPL;
			IDT[i_nr].present = 1;
			IDT[i_nr].hioffset = (uint16)((uint32)i_addr >> 16);
		}
		void loadIDTR(){
			idtr_r.xr_addr[0] = IDT_SIZE;
    		idtr_r.xr_addr[1] = (uint16)((uint32)IDT);
    		idtr_r.xr_addr[2] = (uint16)((uint32)IDT >> 16);
    		asm("lidt idtr_r");
		}
};
*/
//Прерывание таймера
unsigned int tmr = 1;
INT_HANDLER(timer_intr)
{
    if(tmr == 0){
		tmr = 3;
		//kprintf("\nTIMER1");
		//asm("call switch_task");
		//switch_task();
	}
	tmr++;
    if(tmr == 1000)
	tmr = 0;
}



#endif	/* INTERRAPT_H */

